#include "vtkFieldExport_boundary.hpp"

namespace hms::vtk
{

/* StaticValue */
template<typename MeshType>
void writeBoundaryCondition(
	xml::XMLElement* bcElem,
	const StaticValue<MeshType>* bc
){
	bcElem->SetAttribute( "isUniform", bc->isUniform() );
	bcElem->SetAttribute( "isFunction", false );
	matrixToText( bcElem , bc->get() );
}


/* DynamicValue */
template<typename MeshType>
void writeBoundaryCondition(
	xml::XMLElement* bcElem,
	const DynamicValue<MeshType>* bc
){
	bool isUniform { bc->isUniform() };
	bool isFunction { bc->isFunction() };
	bcElem->SetAttribute( "isUniform", isUniform );
	bcElem->SetAttribute( "isFunction", isFunction );

	if ( isFunction ){
		writeFunctions( bcElem, bc->functions() );
	} else { // dynamic value list
		writeTimeSeries( bcElem, bc->values() );
	}
}

#define INSTANTIATE_FOR_ALL_MESHTYPES(MeshType) \
template void writeBoundaryCondition(xml::XMLElement*, const StaticValue <MeshType>*); \
template void writeBoundaryCondition(xml::XMLElement*, const DynamicValue<MeshType>*);
#include "meshInstantiator.hpp"


void writeDefaultBoundaryConditions(
	xml::XMLNode* root,
	const MeshVariant& meshVar
){
	std::visit( [&](const auto& mesh){
		using MeshType = remove_qualifiers<decltype(mesh)>;
		using BC_default = ZeroGradient<MeshType>;
		SWESolver solver {mesh};
		for ( const BoundaryPatch& patch : mesh.boundaryPatches() ){
			for ( Field<MeshType>& field : solver.fields() ){
				field.template setBoundaryCondition<BC_default>( patch );
			}
		}
		writeBoundaryConditions( root, solver );
	}, meshVar);
}

namespace internal
{

std::vector<xml::XMLElement*> boundaryPatchNodes(
	xml::XMLNode* root,
	const std::vector<BoundaryPatch>& boundaryPatches
){
	xml::XMLElement* patchesNode { getBoundaryNode(root) };
	std::vector<xml::XMLElement*> patchNodes ( boundaryPatches.size() );

	for ( size_t i{0}; i < boundaryPatches.size(); ++i ){
		patchNodes[i] = getBoundaryPatch( patchesNode, boundaryPatches[i] );
	}
	return patchNodes;
}

} // namespace internal

} // namespace hms::vtk
